{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Introduction to SyMPC\n",
    "\n",
    "Want to discover SyMPC? You've come just to the right place! This is a short notebook to help you starting with SyMPC.\n",
    "\n",
    "Authors: \n",
    "- George Muraru - [Twitter](https://twitter.com/GeorgeMuraru) - [GitHub](https://github.com/gmuraru)\n",
    "- Théo Ryffel - [Twitter](http://twitter.com/theoryffel) - [GitHub](https://github.com/LaRiffle)\n",
    "\n",
    "SyMPC is a library to perform efficient Secure Multi-Party Computation. It works in combination with PySyft to allow combining a wide range of privacy-preserving techniques."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Therefore, we need to import `syft`, to declare the virtual machines emulating our parties"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import syft as sy\n",
    "\n",
    "sy.logger.remove()\n",
    "import torch\n",
    "\n",
    "from sympc.session import Session\n",
    "from sympc.session import SessionManager\n",
    "from sympc.tensor import MPCTensor"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `MPCTensor` is the tensor that holds reference to the shares owned by the different parties. The `Session` is a key object that stores many information about the current computation, including a reference to the parties involved!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define the virtual machines that would be use in the computation\n",
    "alice_vm = sy.VirtualMachine(name=\"alice\")\n",
    "bob_vm = sy.VirtualMachine(name=\"bob\")\n",
    "charlie_vm = sy.VirtualMachine(name=\"charlie\")\n",
    "\n",
    "# Get clients from each VM\n",
    "alice = alice_vm.get_root_client()\n",
    "bob = bob_vm.get_root_client()\n",
    "charlie = charlie_vm.get_root_client()\n",
    "\n",
    "parties = [alice, bob, charlie]\n",
    "\n",
    "# Setup the session for the computation\n",
    "session = Session(parties=parties)\n",
    "SessionManager.setup_mpc(session)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Secret sharing\n",
    "\n",
    "Ok we are ready to start! Let's define some PyTorch tensors."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 0.1000, -1.0000],\n",
      "        [-4.0000,  4.0000]])\n",
      "tensor([[ 4.0000, -2.5000],\n",
      "        [ 5.0000,  2.0000]])\n"
     ]
    }
   ],
   "source": [
    "# Define the private values to shares\n",
    "x_secret = torch.Tensor([[0.1, -1], [-4, 4]])\n",
    "y_secret = torch.Tensor([[4.0, -2.5], [5, 2]])\n",
    "\n",
    "print(x_secret)\n",
    "print(y_secret)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We then build and distribute secret shares to the parties. We have different ways to do this and all of them deal with `MPCTensor`, an orchestator that wants to do computation on data it does not see."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[MPCTensor]\n",
      "Shape: torch.Size([2, 2])\n",
      "\t| <VirtualMachineClient: alice Client> -> ShareTensorPointer\n",
      "\t| <VirtualMachineClient: bob Client> -> ShareTensorPointer\n",
      "[MPCTensor]\n",
      "Shape: torch.Size([2, 2])\n",
      "\t| <VirtualMachineClient: alice Client> -> ShareTensorPointer\n",
      "\t| <VirtualMachineClient: bob Client> -> ShareTensorPointer\n"
     ]
    }
   ],
   "source": [
    "# 1. Share the secret between some members of the session\n",
    "x = x_secret.share(parties=[alice, bob])\n",
    "y = y_secret.share(parties=[alice, bob])\n",
    "\n",
    "print(x)\n",
    "print(y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[MPCTensor]\n",
      "Shape: torch.Size([2, 2])\n",
      "\t| <VirtualMachineClient: alice Client> -> ShareTensorPointer\n",
      "\t| <VirtualMachineClient: bob Client> -> ShareTensorPointer\n",
      "\t| <VirtualMachineClient: charlie Client> -> ShareTensorPointer\n",
      "[MPCTensor]\n",
      "Shape: torch.Size([2, 2])\n",
      "\t| <VirtualMachineClient: alice Client> -> ShareTensorPointer\n",
      "\t| <VirtualMachineClient: bob Client> -> ShareTensorPointer\n",
      "\t| <VirtualMachineClient: charlie Client> -> ShareTensorPointer\n"
     ]
    }
   ],
   "source": [
    "# 2. Share the secret between all members of a session\n",
    "x = x_secret.share(session=session)\n",
    "y = y_secret.share(session=session)\n",
    "\n",
    "print(x)\n",
    "print(y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[MPCTensor]\n",
      "Shape: torch.Size([2, 2])\n",
      "\t| <VirtualMachineClient: alice Client> -> ShareTensorPointer\n",
      "\t| <VirtualMachineClient: bob Client> -> ShareTensorPointer\n",
      "\t| <VirtualMachineClient: charlie Client> -> ShareTensorPointer\n",
      "[MPCTensor]\n",
      "Shape: torch.Size([2, 2])\n",
      "\t| <VirtualMachineClient: alice Client> -> ShareTensorPointer\n",
      "\t| <VirtualMachineClient: bob Client> -> ShareTensorPointer\n",
      "\t| <VirtualMachineClient: charlie Client> -> ShareTensorPointer\n"
     ]
    }
   ],
   "source": [
    "# 3. Share the secret building an MPCTensor\n",
    "x = MPCTensor(secret=x_secret, session=session)\n",
    "y = MPCTensor(secret=y_secret, session=session)\n",
    "\n",
    "print(x)\n",
    "print(y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can print a `MPCTensor` to have useful information about it, even if its value is private."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Addition\n",
    "\n",
    "Addition on secret shared values is straight forward:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 4.1000, -3.5000],\n",
      "        [ 1.0000,  6.0000]])\n"
     ]
    }
   ],
   "source": [
    "z = x + y\n",
    "\n",
    "print(z.reconstruct())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`.reconstruct()` get back the shares from all the parties and reconstruct the underlying value."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Matrix Multiplication\n",
    "\n",
    "Multiplication or matrix multiplication is also very easy! It relies on the SPDZ protocol, if you are interested to learn more about it, check our [Private AI Series](https://courses.openmined.org/)!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[-4.6000, -2.2500],\n",
      "        [ 4.0000, 18.0000]])\n"
     ]
    }
   ],
   "source": [
    "matmul_result = x @ y\n",
    "\n",
    "print(matmul_result.reconstruct())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### What's next?\n",
    "\n",
    "SyMPC is still under development! We will add here more features as soon they are stable enough, stay tuned! 🕺\n",
    "\n",
    "If you enjoyed this tutorial, show your support by [Starring SyMPC](https://github.com/OpenMined/SyMPC)! 🙏"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
